package cz.pecinovsky.česky.oopnz.utility;
//Příliš žluťoučký kůň úpěl ďábelské ódy
/*******************************************************************************
 *<pre>
 * Předchozí:   Není - toto_je_nově_definovaná_třída
 *              Ttt v projektu Ppp
 * Následující: Prozatím není
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */


////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ Konec ignorovaného počátečního textu +++++


/*******************************************************************************
 * Instance třídy {@code Opakovač} umožňují opakování zadaných akcí
 * na pozadí, tj. be čekání na jejich dokončení.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
public class Opakovač
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    private static final int POŘÁD = -2;
    
    
//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================
//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    /** Opakovač je zrovna zaměstnán. */
    private volatile boolean běží = false;

    /** Byl vydán požadavek k zastavení. */
    private volatile boolean zastavit = false;


    
//== NESOUKROMÉ METODY TŘÍDY ===================================================
//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================
//== ABSTRAKTNÍ METODY =========================================================
//== NESOUKROMÉ  METODY INSTANCÍ ===============================================

    /***************************************************************************
     * Opakuje metodu parametru akce přičemž počet opakování je zadán 
     * v parametru počet.
     *
     * @param  počet Požadovaný počet opakování, 0=pořád
     * @param  akce  Instance, jejíž metoda příkaz() bude opakována
     */
    public synchronized void opakuj( final int počet, final IAkční akce )
    {
        if (běží) {
            throw new RuntimeException(
                "\nDokud je opakovač zaměstnán, není možné jej použít");
        }
        běží     = true;
        zastavit = false;
        new Thread( ""+akce ) {
            int ještě = ((počet == 0) ?  POŘÁD  :  počet);
            @Override
            public void run() {
                do {
                    akce.příkaz();
                }while( ! zastavit  &&
                      ((ještě == POŘÁD)  ||  (--ještě > 0)) );
                běží = false;
            }
        }.start();
    }
    
    
    /***************************************************************************
     * Zastaví opakování prováděná daným opakovačem.
     */
    public synchronized void stop()
    {
        zastavit = true;
    }
    
//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== VNOŘENÉ A VNITŘNÍ TŘÍDY ===================================================
//== TESTY =====================================================================
// 
//     private static class Čítač implements IAkční {
//         int počet;
//         public void příkaz() {
//             System.out.print( počet++ + ((počet%10==0) ? "\n" : "-") );
//             P.čekej( 300 );
//         }
//     }
//     /***************************************************************************
//      *
//      */
//     public static void test() {
//         System.out.println( "\fSTART" );
//         Opakovač o = new Opakovač();
//         Čítač č = new Čítač();
//         o.opakuj( 10, č );
//         P.čekej( 5000 );
//         System.out.println( "\nHotovo" );
//         č = new Čítač();
//         o.opakuj( 0, č );
//         P.zpráva( "Ukončit" );
//         o.stop();
//         System.out.println( "\nKONEC" );
//         P.zpráva( "Ověř ukončení" );
//     }
// 
//     public static void main( String... args ) { test(); }
}
